home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / MSRLEC / DF.ASM next >
Assembly Source File  |  1993-01-31  |  18KB  |  594 lines

  1.      page    ,132
  2. ;-----------------------------Module-Header-----------------------------;
  3. ; Module Name:  DF.ASM - DeltaFrame module
  4. ;
  5. ;   This module contains the DeltaFrame386 routine
  6. ;
  7. ; Exported Functions:   none
  8. ;
  9. ; Public Functions:     DeltaFrame386
  10. ;
  11. ; Public Data:          none
  12. ;
  13. ; General Description:
  14. ;
  15. ; Restrictions:
  16. ;
  17. ;-----------------------------------------------------------------------;
  18.  
  19. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  20. ;
  21. ; (C) Copyright Microsoft Corp. 1991-1993.  All rights reserved.
  22. ;
  23. ; You have a royalty-free right to use, modify, reproduce and 
  24. ; distribute the Sample Files (and/or any modified version) in 
  25. ; any way you find useful, provided that you agree that 
  26. ; Microsoft has no warranty obligations or liability for any 
  27. ; Sample Application Files which are modified. 
  28. ;
  29. ; Unless you got this from the MM Sys BBS, it may not be the most
  30. ; current version.  We are continually improving our samples and
  31. ; their documentation.  Call the BBS at 206 936-4082.
  32. ;
  33. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  34.  
  35.         .xlist
  36.     include cmacros.inc
  37.         include windows.inc
  38.         .list
  39.  
  40.  
  41. RLE_ESCAPE  equ 0
  42. RLE_EOL     equ 0
  43. RLE_EOF     equ 1
  44. RLE_JMP     equ 2
  45. RLE_MINABS  equ 3
  46.  
  47. ; The following structure should be used to access high and low
  48. ; words of a DWORD.  This means that "word ptr foo[2]" -> "foo.hi".
  49.  
  50. LONG    struc
  51. lo    dw    ?
  52. hi    dw    ?
  53. LONG    ends
  54.  
  55. FARPOINTER    struc
  56. off    dw    ?
  57. sel    dw    ?
  58. FARPOINTER      ends
  59.  
  60. wptr    equ     <word ptr>
  61. bptr    equ     <byte ptr>
  62.  
  63. min_ax  macro   REG
  64.         sub     ax,REG
  65.     cwd
  66.     and    ax,dx
  67.         add     ax,REG
  68.     endm
  69.  
  70. max_ax  macro   REG
  71.         sub     ax,REG
  72.     cwd
  73.     not    dx
  74.         and     ax,dx
  75.         add     ax,REG
  76.     endm
  77.  
  78. ; -------------------------------------------------------
  79. ;        DATA SEGMENT DECLARATIONS
  80. ; -------------------------------------------------------
  81.  
  82. sBegin  Data
  83.  
  84. sEnd  Data
  85.  
  86. ; -------------------------------------------------------
  87. ;               CODE SEGMENT DECLARATIONS
  88. ; -------------------------------------------------------
  89.  
  90. ifndef SEGNAME
  91.     SEGNAME equ <_TEXT>
  92. endif
  93.  
  94. createSeg %SEGNAME, CodeSeg, word, public, CODE
  95. .386
  96.  
  97. sBegin  CodeSeg
  98.         assumes cs,CodeSeg
  99.         assumes ds,nothing
  100.         assumes es,nothing
  101.  
  102. ;---------------------------Public-Routine------------------------------;
  103. ; DeltaFrame386
  104. ;
  105. ;   computes the diff of two 8bpp DIBs
  106. ;
  107. ; Entry:
  108. ;       lpbi            bitmap info
  109. ;       pbPrev          previous DIB
  110. ;       pbDib           DIB to compress
  111. ;       pbRle           RLE bits output
  112. ;
  113. ; Returns:
  114. ;       pbRle contains RLE bits for diference
  115. ;       lpbi->biSizeImage contains size
  116. ; Error Returns:
  117. ;    None
  118. ; Registers Preserved:
  119. ;       all
  120. ; Registers Destroyed:
  121. ;       ES,FS,GS,EFLAGS
  122. ; Calls:
  123. ;    nothing
  124. ;-----------------------------------------------------------------------;
  125.         assumes ds,nothing
  126.         assumes es,nothing
  127.  
  128. cProc DeltaFrame386,<FAR,PUBLIC,PASCAL>,<ds>
  129.         ParmD   lpbi            ; bitmap info
  130.         ParmD   pbPrev          ; previous DIB
  131.         ParmD   pbDib           ; DIB to compress
  132.     ParmD    pbRle        ; RLE bits output
  133.         ParmW   MinJumpLength   ; minimum jump allowed
  134.  
  135.         LocalW  curX
  136.         LocalW  curY
  137.  
  138.         LocalW  ImageWidth
  139.         LocalW  ImageHeight
  140.  
  141.         LocalW  JumpX
  142.         LocalW  JumpY
  143.  
  144.         LocalD  NextScan
  145.         LocalD  WidthBytes
  146. cBegin
  147.         pushad                  ; save them all
  148.  
  149.         movzx   eax,ax          ; make all the hiword's zero
  150.         movzx   ebx,bx
  151.         movzx   ecx,cx
  152.         movzx   edx,dx
  153.         movzx   esi,si
  154.         movzx   edi,di
  155.         movzx   ebp,bp
  156.  
  157. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  158. ;   get info from the passed BITMAPINFO and copy it to local
  159. ;   storage.
  160. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  161.         lds     si,lpbi                 ; DS:SI --> BITMAPINFO
  162.  
  163.         mov     ax,wptr [si].biHeight   ; get image size
  164.         mov     ImageHeight,ax
  165.  
  166.         mov     ax,wptr [si].biWidth
  167.         mov     ImageWidth,ax
  168.  
  169.         mov     dx,ax                   ; compute scanline width
  170.         add     ax,3
  171.         and     ax,not 3
  172.  
  173.         movzx   eax,ax
  174.         mov     WidthBytes,eax
  175.  
  176.         sub     ax,dx                   ; amount to get from end of scan to next
  177.         mov     NextScan,eax
  178.  
  179.         xor     ax,ax
  180.         mov     curX,ax
  181.         mov     curY,ax
  182.  
  183.         mov     JumpX,ax
  184.         mov     JumpY,ax
  185.  
  186. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  187. ;   init pointers into buffers, the following registers will be constant
  188. ;   for the entire DeltaFrame process.
  189. ;
  190. ;   register usage:
  191. ;
  192. ;       DS:ESI      -->     DIB
  193. ;       ES:EDI      -->     Rle bits
  194. ;       FS:         -->     Prev DIB
  195. ;
  196. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  197.         lds     si,pbDib
  198.         les     di,pbRle
  199.         lfs     ax,pbPrev
  200.  
  201.         mov     pbPrev,eax
  202.         mov     pbRle,edi
  203.         mov     pbDib,esi
  204.  
  205. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  206. ;
  207. ;   Spatial compression
  208. ;
  209. ;   the frame is to be compressed without relying on the previous frame.
  210. ;
  211. ;   if pbPrev is NULL, no Temporal compression is wanted, just RLE
  212. ;   the DIB and return.
  213. ;
  214. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  215. DeltaFrameSpatial:
  216.         mov     ax,fs
  217.         or      ax,ax                       ; is pbPrev.sel == 0?
  218.         jnz     short DeltaFrameTemporal    ; ...no go do Temporal
  219.  
  220. DeltaFrameSpatialLoop:
  221.         mov     cx,ImageWidth               ; encode entire line
  222.         call    EncodeFragment              ; ...go do it
  223.         add     esi, NextScan               ; point pbDib to next scan
  224.  
  225.         dec     ImageHeight                 ; another scan to do?
  226.         jz      DeltaFrameDone              ; ...no generate EOF and exit
  227.  
  228.         mov     ax,RLE_ESCAPE+(RLE_EOL*256) ; generate EOL, and go for more
  229.         stos    wptr es:[edi]
  230.  
  231.         jmp     short DeltaFrameSpatialLoop
  232.  
  233. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  234. ;
  235. ;   Temporal compression
  236. ;
  237. ;   the frame is to be compressed assuming the previous frame is visible
  238. ;   any pixels that are the same in both frames will be skiped over.
  239. ;
  240. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  241.  
  242. DeltaFrameTemporal:
  243.         xchg    edi,pbPrev              ; fs:edi --> previous DIB
  244.  
  245. DeltaFrameTemporalLoop:
  246.     mov    cx,ImageWidth        ; compute amount of pixels left
  247.     sub    cx,curX         ; on the scanline.
  248.     jz    DeltaFrameEOL        ; are we at EOL?
  249.  
  250.     call    FindFragmentLength    ; calc frag length and jump value
  251.  
  252.     or    ax,ax
  253.     jz    DeltaFrameJump
  254.  
  255. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  256. ;   we have a fragment (ie a part of the image that changed) to encode
  257. ;
  258. ;   first thing we need to do is generate any outstanding jumps we have
  259. ;   in (jump.x, jump.y)
  260. ;
  261. ;    AX is fragment length
  262. ;    BX is jump length
  263. ;
  264. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  265.     add    edi,eax
  266.     xchg    edi,pbPrev        ; es:edi --> RLE bits
  267.  
  268.     push    bx            ; save jump size
  269.     push    ax            ; save fragment size
  270.  
  271.     xor    cx,cx
  272.     xor    bx,bx
  273.     xchg    cx,JumpX        ; check if we need to gen a jump
  274.     xchg    bx,JumpY
  275.  
  276. DeltaFrameDoJump:
  277.         mov     ax,cx                   ; check if we need to gen a jump
  278.     or    ax,bx
  279.     jz    DeltaFrameFragment    ; no jump needed generate a frag.
  280.         js      DeltaFrameNegY          ; negative, need a EOL
  281.  
  282.     mov    ax,RLE_ESCAPE+(RLE_JMP*256)
  283.     stos    wptr es:[edi]
  284.  
  285.     mov    ax,255
  286.     min_ax    cx
  287.     stos    bptr es:[edi]
  288.     sub    cx,ax
  289.  
  290.     mov    ax,255
  291.     min_ax    bx
  292.     stos    bptr es:[edi]
  293.         sub     bx,ax
  294.  
  295.         jmp     short DeltaFrameDoJump
  296.  
  297. DeltaFrameNegY:
  298.     mov    ax,RLE_ESCAPE+(RLE_EOL*256)
  299.     stos    wptr es:[edi]
  300.         mov     cx,curX
  301.         dec     bx
  302.         jmp     short DeltaFrameDoJump
  303.  
  304. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  305. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  306. DeltaFrameFragment:
  307.         pop     cx
  308.         add     curX,cx
  309.     call    EncodeFragment
  310.  
  311.     xchg    edi,pbPrev        ; fs:edi --> Prev DIB
  312.     pop    bx
  313.  
  314. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  315. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  316. DeltaFrameJump:
  317.     add    jumpX,bx
  318.     add    curX,bx
  319.     add    esi,ebx
  320.     add    edi,ebx
  321.         jmp     DeltaFrameTemporalLoop
  322.  
  323. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  324. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  325. DeltaFrameEOL:
  326.         inc     jumpY
  327.         dec     ImageHeight
  328.         jz      DeltaFrameTemporalDone
  329.  
  330.         mov     eax,NextScan
  331.         add     esi,eax
  332.         add     edi,eax
  333.  
  334.         mov     ax,curX             ; jumpX -= curX
  335.         sub     jumpX,ax
  336.  
  337.         xor     ax,ax
  338.         mov     curX,ax
  339.         jz      DeltaFrameTemporalLoop
  340.  
  341. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  342. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  343. DeltaFrameTemporalDone:
  344.         xchg    edi,pbPrev          ; es:edi --> rle data
  345.         errn$   DeltaFrameDone
  346.  
  347. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  348. ;   we are all done!
  349. ;
  350. ;   generate the final EOF and update the biSizeImage field in passed
  351. ;   bitmapinfo and return.
  352. ;
  353. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  354. DeltaFrameDone:
  355.         mov     ax,RLE_ESCAPE+(RLE_EOF*256) ; generate EOF
  356.         stos    wptr es:[edi]
  357.  
  358.         lds     si,lpbi                     ; DS:SI --> BITMAPINFO
  359.  
  360.         sub     edi,pbRle                   ; compute length
  361.         mov     [si].biSizeImage,edi        ; and store it.
  362.  
  363.         mov     wptr [si].biCompression,BI_RLE8
  364.  
  365.         errn$   DeltaFrameExit              ; return to caller
  366.  
  367. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  368. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  369. DeltaFrameExit:
  370.         popad
  371. cEnd
  372.  
  373. ;---------------------------Public-Routine------------------------------;
  374. ; EncodeFragment
  375. ;
  376. ;   RLE encodes a run of 8 bit pixels, no Temporal compression is done.
  377. ;
  378. ; Entry:
  379. ;       SS:BP           --> frame of DeltaFrame386
  380. ;       CX                  number of pixels to RLE
  381. ;       DS:ESI          --> DIB pixels to RLE
  382. ;       ES:EDI          --> place to store RLE data
  383. ;
  384. ; Returns:
  385. ;       DS:ESI          advanced
  386. ;       ES:EDI          advanced
  387. ;       CX              zero.
  388. ; Error Returns:
  389. ;    None
  390. ; Registers Preserved:
  391. ;       EBP,ES,DS,FS,GS
  392. ; Registers Destroyed:
  393. ;       EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS
  394. ;
  395. ;-----------------------------------------------------------------------;
  396.         assumes ds,nothing
  397.         assumes es,nothing
  398.  
  399. EncodeFragment proc near
  400.  
  401.         or      cx,cx                   ; anything at all to do?
  402.         jnz     EncodeFragmentLoop
  403.         jmp     EncodeFragmentExit
  404.  
  405. EncodeFragmentLoop:
  406.         mov     bx,dx
  407.         mov     ax,cx                   ; ax = pixels left
  408.         min_ax  255                     ; ax = min(ax,255)  (255 = maximum run)
  409.         shl     ecx,16                  ; save old cx
  410.         mov     cx,ax                   ; cx = maximum run allowed
  411.         mov     dx,bx
  412.  
  413. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  414. ;   look for a run of same pixels and generate a single RLE run.
  415. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  416. EncodeFragmentSolid:
  417.         xor     ebx,ebx                 ; bx = 0 (run count)
  418.         mov     ah,bptr ds:[esi]        ; get first pixel
  419.  
  420. EncodeFragmentSolidScan:
  421.         inc     bx
  422.         cmp     bx,cx
  423.         je      EncodeFragmentSolidRun
  424.  
  425.     mov    al,bptr ds:[esi+ebx]    ; get pixel
  426.     cmp    al,ah
  427.     je    EncodeFragmentSolidScan
  428.  
  429. EncodeFragmentSolidRun:
  430.         cmp     bx,1                    ; is run greater than one?
  431.         jbe     EncodeFragmentAbs
  432.  
  433. EncodeFragmentSolidEncode:
  434.         mov     al,bl                   ; store solid run (cnt, color)
  435.         stos    wptr es:[edi]
  436.         add     esi,ebx                 ; advance pbDib
  437.  
  438.         shr     ecx,16                  ; restore cx (length)
  439.         sub     cx,bx
  440.         jz      EncodeFragmentExit      ; any pixels left to encode?
  441.         jmp     EncodeFragmentLoop
  442.  
  443. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  444. ;   look for a run of pixels that are not the same
  445. ;   note. we cant generate a abs run less than 3 pixels, so if we have
  446. ;   a abs run <3 encode it as a bunch of count=1 rle runs
  447. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  448. EncodeFragmentAbs:
  449.         cmp     cx,RLE_MINABS           ; enough room left for a min abs run?
  450.         jb      EncodeFragmentSolidEncode
  451.  
  452.         mov     bx,RLE_MINABS-1
  453.  
  454. EncodeFragmentAbsScan:
  455.         inc     bx                      ; add another pixel to the run
  456.  
  457.         ; we want at least 4 pixels in a row to be the same before we
  458.         ; stop ABS mode.  otherwise leaving ABS mode to do a short run
  459.         ; then re-entering ABS mode would be bigger
  460.         ;
  461.         ; if there are not 4 pixels left on the line, encode the max
  462.         ; amount, else the four pixels must be the same
  463.  
  464.         mov     ax,cx                   ; get remaining length
  465.         sub     ax,bx
  466.         xchg    bx,cx                   ; cx = run, bx = max
  467.         cmp     ax,4                    ; are there 4 or more pixels left?
  468.         jb      EncodeFragmentAbsRun    ; no encode the max amount
  469.         xchg    bx,cx                   ; cx = max, bx = run
  470.  
  471.         mov     al,bptr ds:[esi+ebx]    ; get first pixel
  472.  
  473.         cmp     al,bptr ds:[esi+ebx+1]  ; are they the same?
  474.         jne     EncodeFragmentAbsScan
  475.  
  476.         cmp     al,bptr ds:[esi+ebx+2]  ; are they the same?
  477.         jne     EncodeFragmentAbsScan
  478.  
  479.         cmp     al,bptr ds:[esi+ebx+3]  ; are they the same?
  480.         jne     EncodeFragmentAbsScan
  481.  
  482. EncodeFragmentAbsRun:
  483.         xor     al,al                   ; store abs run (0, cnt)
  484.         mov     ah,bl
  485.         stos    wptr es:[edi]
  486.  
  487.         shr     ecx,16                  ; restore cx (length)
  488.         sub     cx,bx                   ; subtract run length from total
  489.  
  490.         xchg    cx,bx
  491.         shr     cx,1
  492.         rep     movs wptr es:[edi], wptr ds:[esi]
  493.         adc     cx,cx
  494.         rep     movs bptr es:[edi], bptr ds:[esi]
  495.         mov     cx,bx
  496.  
  497.         inc     edi                     ; word align RLE data
  498.         and     di,not 1                ; !!! store a zero?
  499.  
  500.         jcxz    EncodeFragmentExit      ; any pixels left to encode?
  501.         jmp     EncodeFragmentLoop      ; and do it again.
  502.  
  503. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  504. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  505. EncodeFragmentExit:
  506.         ret
  507.  
  508. EncodeFragment endp
  509.  
  510. ;---------------------------Public-Routine------------------------------;
  511. ; FindFragmentLength
  512. ;
  513. ;   determine the number of pixels that are not the same
  514. ;   as the previous frame, this run of pixels need to be encoded.
  515. ;
  516. ;   a fragment ends when we run out of pixels or we find a run of similar
  517. ;   pixels greater than MinJumpLength
  518. ;
  519. ; Entry:
  520. ;       SS:BP           --> frame of DeltaFrame386
  521. ;       CX                  number of pixels in line
  522. ;       DS:ESI          --> DIB pixels to RLE
  523. ;       FS:EDI          --> Previous DIB image
  524. ;
  525. ; Returns:
  526. ;    AX        fragment length
  527. ;    BX        run length
  528. ;       CX              remaining pixels in line
  529. ; Error Returns:
  530. ;    None
  531. ; Registers Preserved:
  532. ;       EBP,ES,DS,FS,GS,ESI,EDI
  533. ; Registers Destroyed:
  534. ;       EAX,EBX,ECX,EDX,EFLAGS
  535. ;-----------------------------------------------------------------------;
  536.         assumes ds,nothing
  537.         assumes es,nothing
  538.  
  539. FindFragmentLength proc near
  540.  
  541.     xor    ax,ax
  542.     xor    bx,bx
  543.     jcxz    FindFragmentLengthExit
  544.  
  545. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  546. ;   look for a run of pixels that are not the same
  547. ;   to the previous frame, we must find MinJumpLength pixels that
  548. ;   are the same before we stop.
  549. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -;
  550.         push    bp                      ; save bp
  551.  
  552.         mov     ax,cx
  553.         mov     cx,MinJumpLength        ; put MinJumpLength in HIWORD(ecx)
  554.         shl     ecx,16
  555.         mov     cx,ax
  556.  
  557.         mov     bp,-1
  558.  
  559. FindFragmentLengthLoop1:
  560.         mov     bx,-1
  561.  
  562. FindFragmentLengthLoop:
  563.         inc     bx
  564.     inc    bp            ; another one not the same
  565.     cmp    bp,cx            ; do we got enough?
  566.     je    FindFragmentLengthDone    ; ...yes all done
  567.  
  568.     mov    ah,fs:[edi+ebp]     ; !!!use words!!!
  569.     mov    al,ds:[esi+ebp]
  570.     cmp    al,ah            ; is it exact?
  571.     je    FindFragmentLengthLoop    ; the same keep going (and counting)
  572.  
  573.         rol     ecx,16                  ; ax = HIWORD(ecx) = MinJumpLength
  574.         mov     ax,cx
  575.         rol     ecx,16
  576.         cmp     bx,ax                   ; big enough run to stop?
  577.         jb      FindFragmentLengthLoop1 ; no, zero "same" count and keep going
  578.  
  579. FindFragmentLengthDone:
  580.     sub    cx,bp
  581.     mov    ax,bp            ; return length - jump
  582.     sub    ax,bx
  583.     pop    bp
  584.  
  585. FindFragmentLengthExit:
  586.         movzx   ecx,cx
  587.         ret
  588.  
  589. FindFragmentLength endp
  590.  
  591. sEnd
  592.  
  593. end
  594.